﻿using System;
// obj 和int之间关系
namespace RectangleApplication
{
    class ExecuteRectangle
    {
        static void Main(string[] args)
        {
            int a = 9;
            object obj;
            obj = a;
            obj = 10;
            Console.WriteLine("2: {0}", a);
            Console.WriteLine("1: {0}", obj);
            Console.ReadLine();
        }
    }
}
// 设置值 int a=9; obj=a; 当obj改变不会对 int a 进行改变，object 只是复制了 int a 的值出来然后对其操作而已。不会影响到 int 原来的值。

/*
 
C# 中 String 跟 string 的区别

string 是 C# 中的类，String 是 .net Framework 的类(在 C# IDE 中不会显示蓝色) C# string 映射为 .net Framework 的String 如果用 string, 编译器会把它编译成 String，所以如果直接用 String 就可以让编译器少做一点点工作。

如果使用 C#，建议使用 string，比较符合规范 string 始终代表 System.String(1.x) 或 ::System.String(2.0) ，String 只有在前面有 using System;的时候并且当前命名空间中没有名为 String 的类型（class、struct、delegate、enum）的时候才代表 System.String string 是关键字，String 不是，也就是说 string 不能作为类、结构、枚举、字段、变量、方法、属性的名称，而 String 可以。

String 是 CLR 的类型名称（也算是关键字），而 string 是 C# 中的关键字。string 在编译时候 C# 编译器会默认将其转换为 String，在这里会多增加几行转换的代码。很多时候都是建议使用 CLR 的类型而不要使用 C# 的类型（这是专家的建议）。比如说还有：使用 int 的时候最好使用 Int32 等。很多时候都是一个习惯问题，规范问题。还有一个不同就是在 VS 中表现的颜色不一样：String 是绿色，string 是蓝色。 

 */

/*
 
值类型的特点：

 1.不能从值类型派生新类型，但可以结构实现接口；
 2.值类型不能包含 null 值；
 3.每个值类型都具有一个初始化该类型的默认值的隐式默认构造函数。 

 */

/*
 
每一个值类型都有一个独立的内存区域保存自己的值，调用它的时候调用的是它的值，而引用类型调用的是内存中的地址，比如定义引用类型 a1=10，这时候在内存中保存的是 10，当把 a1 赋给 a2 的时候，他们两个应用的是同一个内存空间，a2 的值会保存为 a1 的值，当把 a2 改为 20 时，应为 a1 和 a2 引用的是同一个所以 a1 也变成 20 了，这是引用类型，值类型是当把 a1 赋给 a2 时会为 a2 在开一块新的空间保存 a1 的值。当把 a2 改成 20 时就会在 a2 的空间保存 20，和 a1 并无什么关系。 

 */

/*
 
就像仓库，仓库里有货架，货架上有编号：A1,A2,A3...................., 这些编号就可以看做是引用类型，现在来了一批货，有 “土豆，黄瓜，西红柿”，这些就是值类型，如果你想让 A1=土豆，那么就要把土豆搬到 A1 里面去，这就叫装箱，装箱需要耗费人力和工时（也就是耗费CPU和内存），同理拆箱就要把对应编号的货物搬出来，也是需要耗费人力和工时。 

 */

/*
 
关于值类型、引用类型以及“栈”跟“堆”的关系

值类型，声明一个值类型的时候，是在“栈”中开辟一个内存空间来存放对应的值，当值类型的值发生改变的时候，则直接修改该内存空间所保存的值。例：

int n1 = 5;
int n2 = n1;
Console.WriteLine(n1 + "  "+ n2);    // 5  5
n2 = 7;
Console.WriteLine(n1 + "  " + n2)    // 5  7
这里首先在“栈”中开辟一个内存空间用来保存 n1 的值 5，接着再在“栈”中开辟一个新的内存空间用来保存 n2 的值 5，所以显示出来的结果是 5 5。然后将 n2 在“栈”中对应的内存空间保存的值修改成 7，故显示出来的结果是 5 7。

引用类型，声明一个引用类型的时候，首先是在“堆”中开辟一个内存空间来存放对应的值，然后在“栈”中开辟一个内存空间用于保存在“堆”中开辟的内存空间的地址。当系统调用引用类型的时候，首先去“栈”中获取到地址，然后根据地址在“堆”中找到对应的内存空间来获取到对应值。像数组这样的引用类型

string[] a1 = new string[]{ "a" , "b" , "c" };
string[] a2 = a1;
for(int i = 0; i < a2.Length; i++)
{
    Console.Write(a2[i] + " ");    //a b c
}
a1[2] = "d";
Console.WriteLine();            //换行
for(int i = 0; i < a2.Length; i++)
{
    Console.Write(a2[i] + " ");    //a b d
}
Console.WriteLine(); 
这里首先是在“堆”中开辟一个内存空间(假设：0X55)用来保存数组a1的值，然后在“栈”中开辟一个内存空间（a1）用于保存地址 0X55。当将 a1 赋给 a2 时，是将地址赋给 a2，即在“栈”中开辟一个内存空间（a2）用于保存地址 0X55，所以输出 a2 的值是 a b c。当将 a1[2]修改成”d”的时候，修改的是“堆”中 0X55 内存空间保存的值，因为 a2 的地址和 a1 的地址一样，所以输出结果是 a b d。

而 string 是一个特殊的引用类型，先看下面代码：

string a = "123";
string b = a; 
Console.WriteLine(a+" "+b);  //123 123
string b = "456";
Console.WriteLine(a+" "+b);  //123 456
和数组类似的，这里首先在“堆”中开辟一个内存空间(假设：0X88)用来保存 a 的值 123，然后在“栈”中开辟一个内存空间（a）用于保存地址 0X88。

和数组不同的是，当将 a 赋给 b 的时候，首先是在“堆”中开辟一个新的内存空间(假设：0X101)用于保存值 123，然后在“栈”中开辟一个内存空间（b）用于保存地址 0X101，所以输出的结果是 123 123。

当修改 b 值时，并不是修改“堆”中 0X101 内存空间的值，而是在“堆”中重新开辟一个新的内存空间(假设：0X210)用于保存 b 修改后的值，然后将 b 在“栈”中对应的内存空间的所保存的地址修改成 0X210，所以输出的结果是 123 456。而“堆”中的 0X101 内存空间将在下次的垃圾回收中被回收利用。 

 */

/*
 
值类型与引用类型的区别：

从内存上看，值类型是在栈中的操作，而引用类型是在堆中的操作。

（导致 => 值类型存取速度快，引用类型存取速度慢。）

从本质上看，值类型表示实际数据，引用类型表示指向存储在内存堆中的数据的指针或引用。

（值类型是具体的那个数值所占用的空间大小，而引用类型是存放那个数值的空间地址。）

从来源上看，值类型继承自System.ValueType，引用类型继承自System.Object。

特别的：结构体是值类型，类和string是引用类型。

当一个值类型转换为对象类型时，则被称为 装箱；另一方面，当一个对象类型转换为值类型时，则被称为 拆箱。

动态类型与对象类型相似，但是对象类型变量的类型检查是在编译时发生的，而动态类型变量的类型检查是在运行时发生的。 

 */